"""
文件读写组件
"""

import typing
from .framework import session_received
from .base import BaseSession, BaseSessionParentType, BaseSessionType
from .utils import to_any, StringValue, callback


@session_received
class File(BaseSession):
    """
    异步读写文件
    调用示例：
        async with await File.open(activity, filename, 'r') as file:
            data = await file.read()
    """
    file_name: str
    mode: str

    name: typing.ClassVar[str] = "File"

    @classmethod
    async def open(cls, parent: BaseSessionParentType, file_name: str, mode: str = 'r'):
        """
        异步打开客户端文件
        """
        _file = await File._create(parent)
        _file.file_name, _file.mode = file_name, mode
        return _file

    @classmethod
    async def _create(cls: typing.Type[BaseSessionType], parent: BaseSessionParentType,
                      *argv: typing.Any, **kwargs: typing.Dict) -> BaseSessionType:
        """此方法由open内部调用"""
        return await super().create(parent, *argv, **kwargs)

    async def on_receive(self, msg):
        name, argv, sid, fid = msg.name, msg.argv, msg.session, msg.future
        match name:
            case 'onRead':
                self.on_read(argv[0], session_id=sid, future_id=fid)
            case 'onReadLine':
                self.on_readline(argv[0], session_id=sid, future_id=fid)
            case 'onExists':
                self.on_exists(argv[0], session_id=sid, future_id=fid)
            case _:
                await super().on_receive(msg)

    async def __aenter__(self):
        await self._open()
        return self

    async def __aexit__(self, _type, _value, _track):
        await self.destroy()

    # def __aiter__(self):
    #     return self

    # async def __anext__(self):
    #     line = await self.readline()
    #     if not line:
    #         raise StopAsyncIteration
    #     return line

    async def _open(self):
        """内部调用，进入with上下文时异步打开文件"""
        f, m = to_any(self.file_name, StringValue), to_any(self.mode, StringValue)
        await self.send_action('open', f, m)

    @callback(str)
    def on_read(self, content: str, session_id: int, future_id: int):
        self.set_action_result(session_id, future_id, content)

    async def read(self):
        return await self.send_action_until_return('read')

    @callback(str)
    def on_readline(self, line: str, session_id: int, future_id: int):
        self.set_action_result(session_id, future_id, line)

    async def readline(self):
        return await self.send_action_until_return('readline')

    async def write(self, data: str):
        await self.send_action('write', to_any(data, StringValue))

    @callback(bool)
    def on_exists(self, res: bool, session_id: int, future_id: int):
        self.set_action_result(session_id, future_id, res)

    async def exists(self):
        return await self.send_action_until_return('exists')

    async def remove(self):
        await self.send_action('remove')
